package com.platform.comm.dto;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.SneakyThrows;
import ma.glasnost.orika.*;
import ma.glasnost.orika.impl.ConfigurableMapper;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.Type;
import ma.glasnost.orika.metadata.TypeFactory;

import java.util.Collection;

/**
 * orika的映射配置类
 *
 * @author lbb created by 2019/1/22 16:31
 */
public class DtoMapper extends ConfigurableMapper {
    @Override
    protected void configure(MapperFactory factory) {
        factory.registerObjectFactory(new JsonNodeObjectFactory(), TypeFactory.valueOf(JsonNode.class));
        factory.getConverterFactory().registerConverter(new JsonNodeConverter());
        factory.registerObjectFactory(new ObjectNodeObjectFactory(), TypeFactory.valueOf(ObjectNode.class));
        factory.getConverterFactory().registerConverter(new ObjectNodeConverter());
        factory.registerObjectFactory(new ArrayNodeObjectFactory(), TypeFactory.valueOf(ArrayNode.class));
        factory.getConverterFactory().registerConverter(new ArrayNodeConverter());
        factory.registerMapper(new CollectionMapper());
    }

    @Override
    protected void configureFactoryBuilder(DefaultMapperFactory.Builder factoryBuilder) {
        factoryBuilder.mapNulls(false);
    }

    static class CollectionMapper extends CustomMapper<Collection, Collection> {
        @SneakyThrows
        @Override
        public void mapAtoB(Collection a, Collection b, MappingContext context) {
            b.clear();
            b.addAll(a);
        }
    }

    static class JsonNodeObjectFactory implements ObjectFactory<JsonNode> {
        @SneakyThrows
        @Override
        public JsonNode create(Object o, MappingContext mappingContext) {
            JsonMapper jsonMapper = new JsonMapper();
            return jsonMapper.valueToTree(o);
        }
    }

    static class JsonNodeConverter extends CustomConverter<JsonNode, JsonNode> {
        @Override
        public JsonNode convert(JsonNode jsonNodes, Type<? extends JsonNode> type, MappingContext mappingContext) {
            return jsonNodes;
        }
    }

    static class ObjectNodeObjectFactory implements ObjectFactory<ObjectNode> {
        @SneakyThrows
        @Override
        public ObjectNode create(Object o, MappingContext mappingContext) {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.valueToTree(o);
        }
    }

    static class ObjectNodeConverter extends CustomConverter<ObjectNode, ObjectNode> {
        @Override
        public ObjectNode convert(ObjectNode objectNode, Type<? extends ObjectNode> type, MappingContext mappingContext) {
            return objectNode;
        }
    }

    static class ArrayNodeObjectFactory implements ObjectFactory<ArrayNode> {
        @SneakyThrows
        @Override
        public ArrayNode create(Object o, MappingContext mappingContext) {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.valueToTree(o);
        }
    }

    static class ArrayNodeConverter extends CustomConverter<ArrayNode, ArrayNode> {
        @Override
        public ArrayNode convert(ArrayNode objectNode, Type<? extends ArrayNode> type, MappingContext mappingContext) {
            return objectNode;
        }
    }
}


